package com.libbase.datarepository

import android.util.Log
import com.libbase.Wrapper
import com.libbase.cast
import io.reactivex.rxjava3.disposables.CompositeDisposable
import io.reactivex.rxjava3.kotlin.addTo
import io.reactivex.rxjava3.subjects.PublishSubject

abstract class DataRepository<T>(data: T?) : DataRepositoryInterface {
    companion object {
        const val TAG = "DataRepository"
    }

    private val compositeDisposable = CompositeDisposable()

    var data: T? = data
        private set

    override var dataChangeCallBack: ((encodeData: Any?) -> Unit)? = null

    override var itemChangeCallBack: ((encodeItem: Any?) -> Unit)? = null

    val dataObserver: PublishSubject<Wrapper<T>> = PublishSubject.create()

    abstract fun decode(data: Any): T?

    abstract fun encode(data: T): Any

    init {
        dataObserver
            .subscribe({
                dataChangeCallBack?.let {
                    it(getEncodeData())
                }
            }, {
                Log.e(TAG, it.message ?: "DataRepository error!")
            })
            .addTo(compositeDisposable)
    }

    override fun setEncodeData(data: Any?) {
        val dataMap: Map<String, Any>? = cast(data)
        set(dataMap?.let { decode(it) })
    }

    override fun getEncodeData(): Any? {
        val data: T = this.data ?: return null

        return encode(data)
    }

    fun set(data: T?) {
        this.data = data

        save()

        dataObserver.onNext(Wrapper(this.data))
    }
}